const { ethers, upgrades } = require("hardhat");
const fs = require("fs");

async function main() {
    console.log("🚀 开始本地部署NFT拍卖市场（测试环境）...");

    // 获取部署者账户
    const [deployer, seller, bidder1, bidder2, treasury, artist] = await ethers.getSigners();
    console.log("部署者地址:", deployer.address);
    console.log("部署者余额:", ethers.utils.formatEther(await deployer.getBalance()), "ETH");

    try {
        // 1. 部署模拟价格聚合器（Mock Chainlink Price Feed）
        console.log("\n📊 部署模拟ETH/USD价格聚合器...");
        const MockAggregator = await ethers.getContractFactory("MockV3Aggregator");
        const mockETHUSDFeed = await MockAggregator.deploy(
            8,                                      // 8位小数精度
            ethers.utils.parseUnits("2000", 8)     // 初始价格$2000
        );
        await mockETHUSDFeed.deployed();
        console.log("✅ MockETHUSDFeed 部署完成:", mockETHUSDFeed.address);

        // 2. 部署价格预言机合约（使用Mock Feed）
        console.log("\n💰 部署价格预言机合约...");
        const PriceOracle = await ethers.getContractFactory("PriceOracle");
        const priceOracle = await upgrades.deployProxy(
            PriceOracle,
            [mockETHUSDFeed.address],
            {
                initializer: 'initialize',
                kind: 'uups'
            }
        );
        await priceOracle.deployed();
        console.log("✅ PriceOracle 部署完成:", priceOracle.address);

        // 3. 部署NFT合约
        console.log("\n🎨 部署NFT合约...");
        const AuctionNFT = await ethers.getContractFactory("AuctionNFT");
        const auctionNFT = await upgrades.deployProxy(
            AuctionNFT,
            [
                "拍卖艺术品集合",                        // NFT名称
                "AAC",                                 // NFT符号
                artist.address,                        // 版税接收者
                250,                                   // 版税：2.5%
                ethers.utils.parseEther("0.01"),       // 铸造价格：0.01 ETH
                10000                                  // 最大供应量：10000个
            ],
            {
                initializer: 'initialize',
                kind: 'uups'
            }
        );
        await auctionNFT.deployed();
        console.log("✅ AuctionNFT 部署完成:", auctionNFT.address);

        // 4. 部署拍卖工厂合约
        console.log("\n🏭 部署拍卖工厂合约...");
        const AuctionFactory = await ethers.getContractFactory("AuctionFactory");
        const auctionFactory = await upgrades.deployProxy(
            AuctionFactory,
            [
                priceOracle.address,                   // 价格预言机地址
                treasury.address                       // 财务地址（手续费接收者）
            ],
            {
                initializer: 'initialize',
                kind: 'uups'
            }
        );
        await auctionFactory.deployed();
        console.log("✅ AuctionFactory 部署完成:", auctionFactory.address);

        // 5. 部署Mock CCIP路由器（用于跨链测试）
        console.log("\n🔗 部署Mock CCIP路由器...");
        const MockCCIPRouter = await ethers.getContractFactory("MockCCIPRouter");
        const mockCCIPRouter = await MockCCIPRouter.deploy();
        await mockCCIPRouter.deployed();
        console.log("✅ MockCCIPRouter 部署完成:", mockCCIPRouter.address);

        // 6. 部署简单跨链拍卖合约
        console.log("\n🌉 部署简单跨链拍卖合约...");
        const SimpleCrossChainAuction = await ethers.getContractFactory("SimpleCrossChainAuction");
        const simpleCrossChainAuction = await SimpleCrossChainAuction.deploy(
            mockCCIPRouter.address                     // 使用Mock CCIP路由器
        );
        await simpleCrossChainAuction.deployed();
        console.log("✅ SimpleCrossChainAuction 部署完成:", simpleCrossChainAuction.address);

        // 7. 配置合约关系
        console.log("\n⚙️ 配置合约关系...");

        // 设置NFT合约的拍卖市场地址
        await auctionNFT.setAuctionMarket(auctionFactory.address);
        console.log("✅ NFT合约已配置拍卖市场地址");

        // 配置跨链拍卖支持的链
        const ETHEREUM_CHAIN_SELECTOR = 5009297550715157269n;
        const POLYGON_CHAIN_SELECTOR = 4051577828743386545n;

        await simpleCrossChainAuction.addSupportedChain(ETHEREUM_CHAIN_SELECTOR);
        await simpleCrossChainAuction.addSupportedChain(POLYGON_CHAIN_SELECTOR);
        console.log("✅ 跨链拍卖已配置支持链");

        // 8. 验证部署
        console.log("\n🔍 验证合约部署...");

        const oracleOwner = await priceOracle.owner();
        const nftName = await auctionNFT.name();
        const factoryOwner = await auctionFactory.owner();
        const ethPrice = await priceOracle.getETHPrice();

        console.log("价格预言机所有者:", oracleOwner);
        console.log("NFT名称:", nftName);
        console.log("工厂合约所有者:", factoryOwner);
        console.log("当前ETH价格:", ethers.utils.formatUnits(ethPrice, 8), "USD");

        // 9. 铸造测试NFT
        console.log("\n🎨 铸造测试NFT...");

        // Artist铸造NFT用于拍卖
        const mintTx1 = await auctionNFT.connect(artist).mintNFT(
            artist.address,
            "ipfs://QmTestArtworkMetadata1",
            { value: ethers.utils.parseEther("0.01") }
        );
        await mintTx1.wait();
        console.log("✅ 艺术家NFT铸造完成 (Token ID: 1)");

        // Seller铸造NFT用于拍卖
        const mintTx2 = await auctionNFT.connect(seller).mintNFT(
            seller.address,
            "ipfs://QmTestArtworkMetadata2",
            { value: ethers.utils.parseEther("0.01") }
        );
        await mintTx2.wait();
        console.log("✅ 卖家NFT铸造完成 (Token ID: 2)");

        // 验证NFT所有权
        const nft1Owner = await auctionNFT.ownerOf(1);
        const nft2Owner = await auctionNFT.ownerOf(2);
        const totalSupply = await auctionNFT.totalSupply();

        console.log("NFT 1 所有者:", nft1Owner);
        console.log("NFT 2 所有者:", nft2Owner);
        console.log("总供应量:", totalSupply.toString());

        // 10. 输出部署信息
        console.log("\n" + "=".repeat(80));
        console.log("🎉 NFT拍卖市场本地部署完成!");
        console.log("=".repeat(80));
        console.log("📊 MockETHUSDFeed     :", mockETHUSDFeed.address);
        console.log("💰 PriceOracle        :", priceOracle.address);
        console.log("🎨 AuctionNFT         :", auctionNFT.address);
        console.log("🏭 AuctionFactory     :", auctionFactory.address);
        console.log("🔗 MockCCIPRouter     :", mockCCIPRouter.address);
        console.log("🌉 SimpleCrossChainAuction:", simpleCrossChainAuction.address);
        console.log("=".repeat(80));

        // 11. 生成账户信息
        console.log("\n👥 测试账户信息:");
        console.log("🏗️  部署者 (Owner)    :", deployer.address);
        console.log("💰 卖家 (Seller)     :", seller.address);
        console.log("🎯 竞拍者1 (Bidder1)  :", bidder1.address);
        console.log("🎯 竞拍者2 (Bidder2)  :", bidder2.address);
        console.log("🏛️  财务 (Treasury)   :", treasury.address);
        console.log("🎨 艺术家 (Artist)    :", artist.address);

        // 12. 生成使用示例代码
        console.log("\n📝 快速使用示例:");
        console.log(`
// === 1. 连接合约 ===
const auctionNFT = await ethers.getContractAt("AuctionNFT", "${auctionNFT.address}");
const auctionFactory = await ethers.getContractAt("AuctionFactory", "${auctionFactory.address}");

// === 2. 授权NFT给拍卖工厂 ===
await auctionNFT.connect(artist).setApprovalForAll("${auctionFactory.address}", true);

// === 3. 创建拍卖 ===
const createTx = await auctionFactory.connect(artist).createAuction(
    "${auctionNFT.address}",              // NFT合约地址
    1,                                    // Token ID
    ethers.utils.parseEther("0.1"),       // 起拍价：0.1 ETH
    ethers.utils.parseEther("0.2"),       // 保留价：0.2 ETH
    86400                                 // 时长：1天
);

// === 4. 获取拍卖合约地址 ===
const receipt = await createTx.wait();
const auctionAddress = receipt.events.find(e => e.event === "AuctionCreated").args.auctionContract;
const auction = await ethers.getContractAt("NFTAuction", auctionAddress);

// === 5. 参与出价 ===
await auction.connect(bidder1).bidWithETH({ value: ethers.utils.parseEther("0.12") });
await auction.connect(bidder2).bidWithETH({ value: ethers.utils.parseEther("0.15") });

// === 6. 查看拍卖状态 ===
const status = await auction.getAuctionStatus();
console.log("拍卖状态:", status);
        `);

        // 13. 保存部署信息到JSON文件
        const deploymentInfo = {
            network: "localhost",
            chainId: 31337,
            timestamp: new Date().toISOString(),
            deployer: deployer.address,
            contracts: {
                MockETHUSDFeed: mockETHUSDFeed.address,
                PriceOracle: priceOracle.address,
                AuctionNFT: auctionNFT.address,
                AuctionFactory: auctionFactory.address,
                MockCCIPRouter: mockCCIPRouter.address,
                SimpleCrossChainAuction: simpleCrossChainAuction.address
            },
            accounts: {
                deployer: deployer.address,
                seller: seller.address,
                bidder1: bidder1.address,
                bidder2: bidder2.address,
                treasury: treasury.address,
                artist: artist.address
            },
            testNFTs: {
                artistNFT: { tokenId: 1, owner: artist.address },
                sellerNFT: { tokenId: 2, owner: seller.address }
            },
            mockData: {
                ethPrice: "2000",
                ethPriceFeed: mockETHUSDFeed.address,
                supportedChains: [ETHEREUM_CHAIN_SELECTOR.toString(), POLYGON_CHAIN_SELECTOR.toString()]
            }
        };

        fs.writeFileSync(
            'deployment-local.json',
            JSON.stringify(deploymentInfo, null, 2)
        );
        console.log("\n💾 本地部署信息已保存到 deployment-local.json");

        // 14. 返回合约实例以供测试使用
        return {
            mockETHUSDFeed,
            priceOracle,
            auctionNFT,
            auctionFactory,
            mockCCIPRouter,
            simpleCrossChainAuction,
            accounts: { deployer, seller, bidder1, bidder2, treasury, artist }
        };

    } catch (error) {
        console.error("\n❌ 部署失败:", error.message);
        if (error.stack) {
            console.error("错误堆栈:", error.stack);
        }
        process.exit(1);
    }
}

// 导出main函数以供测试使用
module.exports = { deployLocal: main };

// 如果直接运行此脚本
if (require.main === module) {
    main()
        .then(() => {
            console.log("\n🎊 本地部署完成!");
            process.exit(0);
        })
        .catch((error) => {
            console.error("❌ 部署脚本执行失败:", error);
            process.exit(1);
        });
}
